package com.mobilesales.android.activities.clients;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TextView;

import com.mobilesales.android.R;
import com.mobilesales.android.activities.ModelActivity;
import com.mobilesales.android.adapters.GroupAdapter;
import com.mobilesales.android.adapters.SlidingMenus;
import com.mobilesales.android.database.ClientManager;
import com.mobilesales.android.database.ParamManager;
import com.mobilesales.android.model.clients.Client;
import com.mobilesales.android.model.clients.ClientGroup;
import com.mobilesales.android.model.dictionary.Dictionary;
import com.mobilesales.android.model.exceptions.ServiceUnavailableException;
import com.mobilesales.android.model.params.FieldType;
import com.mobilesales.android.model.params.Param;
import com.mobilesales.android.model.params.ParamType;
import com.mobilesales.android.services.ClientServiceClient;
import com.mobilesales.android.util.LogFlags;
import com.mobilesales.android.util.MessageBox;
import com.mobilesales.android.util.Settings;

public class StoreClient extends ModelActivity<Client> {
	protected EditText nameTxt;
	protected EditText name2Txt;
	protected Spinner groupSelect;
	protected EditText nipTxt;
	protected EditText streetTxt;
	protected EditText zipcodeTxt;
	protected EditText cityTxt;
	protected EditText phoneTxt;
	protected EditText faxTxt;
	protected EditText infoTxt;
	protected EditText info2Txt;
	protected EditText debtsTxt;
	protected CheckBox isSupplierCB;
	private GroupAdapter groupAdapter;
	private Map<Param, View> editors = new HashMap<Param, View>();
	private int clientId = 0;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.client_add);
		new SlidingMenus(this);
		this.nameTxt = ((EditText) findViewById(R.id.clientNameTxt));
		this.name2Txt = ((EditText) findViewById(R.id.clientName2Txt));
		this.groupSelect = ((Spinner) findViewById(R.id.groupSelectSpinner));
		this.nipTxt = ((EditText) findViewById(R.id.clientNipTxt));
		this.streetTxt = ((EditText) findViewById(R.id.clientStreetTxt));
		this.zipcodeTxt = ((EditText) findViewById(R.id.clientZipcodeTxt));
		this.cityTxt = ((EditText) findViewById(R.id.clientCityTxt));
		this.phoneTxt = ((EditText) findViewById(R.id.clientPhoneTxt));
		this.faxTxt = ((EditText) findViewById(R.id.clientFaxTxt));
		this.infoTxt = ((EditText) findViewById(R.id.clientInfoTxt));
		this.info2Txt = ((EditText) findViewById(R.id.clientInfo2Txt));
		this.debtsTxt = ((EditText) findViewById(R.id.clientDebtsTxt));
		this.isSupplierCB = ((CheckBox) findViewById(R.id.clientIsSupplierCheck));

		Bundle bundle = getIntent().getExtras();
		if ((bundle != null) && (bundle.containsKey("clientId"))) {
			clientId = bundle.getInt("clientId");
		}

		this.loadItem(clientId);
	}

	public void store(View v) {
		if (validate()) {
			Client client = null;
			client = (Client) getModel();
			if (client == null) {
				client = new Client();
			}
			client.City = this.cityTxt.getText().toString();
			client.Name = this.nameTxt.getText().toString();
			client.Name2 = this.name2Txt.getText().toString();
			client.Group = ((ClientGroup) this.groupSelect.getSelectedItem());
			client.Nip = this.nipTxt.getText().toString();
			client.Street = this.streetTxt.getText().toString();
			client.Zipcode = this.zipcodeTxt.getText().toString();
			client.City = this.cityTxt.getText().toString();
			client.Phone = this.phoneTxt.getText().toString();
			client.Fax = this.faxTxt.getText().toString();
			client.Info = this.infoTxt.getText().toString();
			client.Info2 = this.info2Txt.getText().toString();
			client.Debts = Double.parseDouble(this.debtsTxt.getText()
					.toString());
			client.IsSupplier = Boolean.valueOf(this.isSupplierCB.isChecked());
			client.Params = parseParams();
			// new Dictionary<Param,String>();
			super.setModel(client);
			if (save(client)) {
				this.setResult(Activity.RESULT_OK);
				finish();
			} else
				MessageBox.show(this, getString(R.string.ErrorSave));
		} else {
			MessageBox.show(this, getString(R.string.ErrorValidate));
		}
	}

	private void loadItem(int clientId) {
		List<ClientGroup> groups = getClientGroups();
		if (groups != null) {
			this.groupAdapter = new GroupAdapter(this,
					R.layout.select_list_item, groups);
			this.groupSelect.setAdapter(this.groupAdapter);
			this.fixSpinner(groupSelect);
		} else {
			MessageBox.show(this, getString(R.string.ErrorClientGroupList));
			finish();
		}

		if (clientId != 0) {
			Client client = getClient(clientId);
			if (client != null) {
				setModel(client);
				((Button) findViewById(R.id.storeBtn))
						.setText(getString(R.string.Save));
			} else {
				MessageBox.show(this, getString(R.string.ErrorClient));
				finish();
			}
		} else {
			List<Param> params = getClientParams();
			Dictionary<Param, String> dict = new Dictionary<Param, String>();
			if (params != null) {
				for (Param param : params) {
					dict.addValue(param, null);
				}
				// drawParams(dict);
			} else {
				MessageBox.show(this, getString(R.string.ErrorClientParams));
				finish();
			}
		}
	}

	@Override
	protected void setModel(Client client) {
		super.setModel(client);
		this.cityTxt.setText(client.City);
		this.nameTxt.setText(client.Name);
		this.name2Txt.setText(client.Name2);
		this.groupSelect.setSelection(this.groupAdapter
				.getPosition(client.Group.Id));
		this.nipTxt.setText(client.Nip);
		this.streetTxt.setText(client.Street);
		this.zipcodeTxt.setText(client.Zipcode);
		this.cityTxt.setText(client.City);
		this.phoneTxt.setText(client.Phone);
		this.faxTxt.setText(client.Fax);
		this.infoTxt.setText(client.Info);
		this.info2Txt.setText(client.Info2);
		this.debtsTxt.setText(String.valueOf(client.Debts));
		this.isSupplierCB.setChecked(client.IsSupplier.booleanValue());
		// drawParams(client.Params);
	}

	private Dictionary<Param, String> parseParams() {
		Dictionary<Param, String> paramValues = new Dictionary<Param, String>();
		for (Param param : this.editors.keySet()) {
			View editor = (View) this.editors.get(param);
			String val = null;
			if (param.FieldType == FieldType.Boolean) {
				val = String.valueOf(((CheckBox) editor).isChecked());
			} else if (param.FieldType == FieldType.Dictionary) {
				val = (String) ((Spinner) editor).getSelectedItem();
			} else {
				val = ((EditText) editor).getText().toString();
				if (val.equals(""))
					val = null;
			}
			paramValues.addValue(param, val);
		}
		return paramValues;
	}

	/**
	 * 
	 * @param params
	 */
	private void drawParams(Dictionary<Param, String> params) {
		TableLayout table = (TableLayout) findViewById(R.id.fields);
		ArrayList<Spinner> spinners = new ArrayList<Spinner>();
		if (params != null) {
			for (Param param : params.getKeys()) {
				LinearLayout tr = new LinearLayout(this);
				tr.setOrientation(LinearLayout.VERTICAL);
				LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(
						LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
				llp.setMargins(5, 5, 5, 5);
				tr.setLayoutParams(llp);

				TextView label = new TextView(this);
				label.setText(param.DisplayName);
				llp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
						LayoutParams.WRAP_CONTENT);
				llp.setMargins(0, 0, 15, 0);
				label.setLayoutParams(llp);
				tr.addView(label);

				String val = (String) params.getValue(param);

				if ((val == null) || (val.equals(""))) {
					val = param.DefaultValue != null ? param.DefaultValue : "";
				}
				if (param.FieldType == FieldType.Boolean) {
					boolean b = Boolean.parseBoolean(val.toLowerCase());
					CheckBox editor = new CheckBox(this);
					editor.setChecked(b);
					this.editors.put(param, editor);
					tr.addView(editor);
				} else if (param.FieldType == FieldType.Dictionary) {
					String dictString = param.DefaultValue;
					if (!param.IsRequired) {
						dictString = String.format(" ;%s",
								new Object[] { dictString });
					}

					String[] values = dictString.split(";");
					int selectedIdx = 0;
					for (int i = 0; i < values.length; i++) {
						if (val.equals(values[i])) {
							selectedIdx = i;
						}
					}
					ArrayAdapter<String> dictAdapter = new ArrayAdapter<String>(
							this, R.layout.select_list_item,
							R.id.selectItemTxt, values);

					Spinner dictSpinner = new Spinner(this);
					dictSpinner.setAdapter(dictAdapter);
					dictSpinner.setSelection(selectedIdx);
					this.editors.put(param, dictSpinner);
					spinners.add(dictSpinner);
					tr.addView(dictSpinner);
				} else {
					final EditText editor = new EditText(this);
					editor.setText(val);

					if ((param.FieldType == FieldType.String)
							&& (param.MaxLength != null)) {
						final int maxLength = param.MaxLength.intValue();
						editor.setOnKeyListener(new View.OnKeyListener() {
							public boolean onKey(View v, int keyCode,
									KeyEvent event) {
								String Name = editor.getText().toString();

								return (Name.length() >= maxLength)
										&& (keyCode != 67);
							}

						});
					}

					this.editors.put(param, editor);
					editor.setWidth(200);
					tr.addView(editor);
				}
				table.addView(tr);
			}
		}
		table.invalidate();
		for (Spinner s : spinners) {
			this.fixSpinner(s);
		}

	}

	private boolean save(Client client) {
		try {
			ClientServiceClient clientService = new ClientServiceClient(
					Settings.ClientService());
			Log.i("conf", Settings.ClientService().getServiceURL());
			clientService.storeClient(client);
			return true;
		} catch (ServiceUnavailableException e) {
			Log.e(LogFlags.RestService, e.getMessage(), e);
		}
		return false;
	}

	private Client getClient(int clientId) {
		ClientManager manager = new ClientManager(this);
		Client result = manager.GetClient(clientId);
		manager.Close();
		return result;
	}

	private List<Param> getClientParams() {
		ParamManager manager = new ParamManager(this);
		List<Param> result = manager.GetParamList(ParamType.Client);
		manager.Close();
		return result;
	}

	private List<ClientGroup> getClientGroups() {
		ClientManager manager = new ClientManager(this);
		List<ClientGroup> result = manager.GetClientGroupList();
		manager.Close();
		return result;
	}

	@Override
	protected boolean validate() {
		ArrayList<EditText> invalidFields = new ArrayList<EditText>();
		if (this.nameTxt.getText().toString().equals(""))
			invalidFields.add(this.nameTxt);
		if (this.nipTxt.getText().toString().equals(""))
			invalidFields.add(this.nipTxt);
		if (this.streetTxt.getText().toString().equals(""))
			invalidFields.add(this.streetTxt);
		if (this.zipcodeTxt.getText().toString().equals(""))
			invalidFields.add(this.zipcodeTxt);
		if (this.cityTxt.getText().toString().equals(""))
			invalidFields.add(this.cityTxt);
		if (this.phoneTxt.getText().toString().equals("")) {
			invalidFields.add(this.phoneTxt);
		}

		for (EditText field : invalidFields) {
			field.setError(getString(R.string.ErrorRequired));
		}

		String debts = this.debtsTxt.getText().toString();
		if (!debts.equals("")) {
			try {
				Double.parseDouble(debts);
			} catch (Exception ex) {
				invalidFields.add(this.debtsTxt);
				debtsTxt.setError(getString(R.string.ErrorInvalidValue));
			}
		} else
			this.debtsTxt.setText("0");

		for (Param param : editors.keySet()) {
			if ((param.FieldType == FieldType.Boolean)
					|| (param.FieldType == FieldType.Dictionary))
				continue;
			EditText editor = (EditText) this.editors.get(param);
			String val = editor.getText().toString();
			if ((param.IsRequired) && (val.equals(""))) {
				invalidFields.add(editor);
				editor.setError(getString(R.string.ErrorRequired));
			} else if (param.FieldType == FieldType.Double) {
				try {
					Double.parseDouble(val);
				} catch (Exception ex) {
					invalidFields.add(editor);
					editor.setError(getString(R.string.ErrorInvalidValue));
				}
			} else {
				if (param.FieldType != FieldType.Integer)
					continue;
				try {
					Integer.parseInt(val);
				} catch (Exception ex) {
					invalidFields.add(editor);
					editor.setError(getString(R.string.ErrorInvalidValue));
				}

			}

		}
		return invalidFields.size() == 0;
	}

	public void refresh() {
		this.getHandler().post(new Runnable() {
			public void run() {
				loadItem(clientId);
			}
		});
	}
}